package com.study.service.impl;

import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.study.common.Const;
import com.study.common.ResponseResult;
import com.study.dao.OrderDao;
import com.study.dao.OrderDetailDao;
import com.study.dao.PayInfoDao;
import com.study.dao.ShopCarDao;
import com.study.entity.Order;
import com.study.entity.OrderDetail;
import com.study.entity.PayInfo;
import com.study.service.OrderService;
import com.study.utils.QiniuUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * Created by Administrator on 2017/11/6/006.
 * 订单业务类
 */
@Service
public class OrderServiceImpl implements OrderService {

    private Logger logger= LoggerFactory.getLogger(OrderServiceImpl.class);

    private static AlipayTradeService tradeService;

    static {
        /** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
         *  Configs会读取classpath下的zfbinfo.properties文件配置信息，如果找不到该文件则确认该文件是否在classpath目录
         */
        Configs.init("zfbinfo.properties");

        /** 使用Configs提供的默认参数
         *  AlipayTradeService可以使用单例或者为静态成员对象，不需要反复new
         */
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
    }
    @Value("${file_server}")
    private String path;//文件服务器地址
    @Value("${alipay_callback}")
    private String alipay_callback;

    @Autowired
    private OrderDetailDao orderDetailDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ShopCarDao shopCarDao;
    @Autowired
    private PayInfoDao payInfoDao;

    @Override
    public String addOrder(Order order) {
        Order save = orderDao.save(order);
        return save.getOrderId();
    }

    public List<Order> getOrderList(Integer uid) {
        return orderDao.findAllByUid(uid);
    }

    public List<OrderDetail> getOrderDetailList(String orderId) {
        return orderDetailDao.findAllByOrOrderId(orderId);
    }

    @Override
    public ResponseResult pay(String orderId, Integer uid) {
        Order order = orderDao.findByOrderId(orderId);
        if (order == null) {
            throw new RuntimeException("没有该订单");
        }
        //订单编号
        String outTradeNo = order.getOrderId();
        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = new StringBuilder().append("happymmall扫码支付,订单号:").append(outTradeNo).toString();
        //订单金额
        String totalAmount = order.getTotalPrice().toString();
        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = new StringBuilder().append("订单").append(outTradeNo).append("购买商品共").append(totalAmount).append("元").toString();
        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";
        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";
        // 支付超时，定义为120分钟
        String timeoutExpress = "120m";
        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        //ExtendParams extendParams = new ExtendParams();
        //extendParams.setSysServiceProviderId("2088100200300400500");

        //从数据库获取订单详情
        List<OrderDetail> list = orderDetailDao.findAllByOrOrderId(order.getOrderId());
        //将订单详情封装成支付宝要求的GoodsDetail类
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        for (OrderDetail orderDetail : list) {
            GoodsDetail goodsDetail = GoodsDetail.newInstance(orderDetail.getGoodsId().toString(),
                    orderDetail.getGoodsName(),
                    orderDetail.getPrice().longValue() * 100,
                    orderDetail.getNum());
            goodsDetailList.add(goodsDetail);
        }

        //构造订单预支付请求
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setOutTradeNo(outTradeNo)
                .setSubject(subject)
                .setTotalAmount(totalAmount)
                .setStoreId(storeId)
                .setBody(body)
                .setOperatorId(operatorId)
                .setGoodsDetailList(goodsDetailList)
                .setTimeoutExpress(timeoutExpress)
                .setNotifyUrl(alipay_callback);//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置;
        //发送预支付请求
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        //得到预支付请求结果
        AlipayTradePrecreateResponse res = result.getResponse();
        //通过返回码判断请求结果
        switch (result.getTradeStatus()) {
            case SUCCESS:
                logger.debug("==========支付宝预下单成功=========");
                //删除购物车
                shopCarDao.deleteAllByUid(uid);
                //生成文件名
                String fileName = String.format("images%sqr-%s.png", File.separator, res.getOutTradeNo());
                //文件地址
                String filePath = new StringBuilder(path).append(fileName).toString();
                //生成二维码图片文件
                ZxingUtils.getQRCodeImge(res.getQrCode(), 256, filePath);
                try {
                    fileName = QiniuUtils.upload(filePath);//上传到七牛云
                    filePath="http://oyirtj6m7.bkt.clouddn.com/"+fileName;
                } catch (IOException e) {
                    throw new RuntimeException("上传二维码失败"+e);
                }
                //将二维码文件路径返回
                return new ResponseResult(0, "支付宝预下单成功", filePath);
            case FAILED:
                logger.error("==========支付宝预下单失败=========");
                return new ResponseResult(0, "支付宝预下单失败", res.getMsg());
            case UNKNOWN:
                logger.error("==========支付宝预下单异常=========");
                return new ResponseResult(0, "支付宝预下单异常", res.getMsg());
        }
        return null;
    }
    @Transactional
    public void aliCallback(Map<String,String> params){
        String orderNo = params.get("out_trade_no");//自己的订单编号
        String tradeNo = params.get("trade_no");//支付宝交易编号
        String tradeStatus = params.get("trade_status");//交易状态
        Order order = orderDao.findByOrderId(orderNo);
        if (order == null) {
            //1 判断是否存在
            throw new RuntimeException("订单不存在，可能被伪造");
        }
        if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){
            //2 判断是否重复下单
            throw new RuntimeException("支付宝重复调用");
        }
        if(Const.AlipayCallback.TRADE_STATUS_TRADE_SUCCESS.equals(tradeStatus)){
            //3 修改订单状态
            order.setPaymentTime(new Date());
            order.setStatus(Const.OrderStatusEnum.PAID.getCode());
            orderDao.save(order);
        }
        //添加支付信息
        PayInfo payInfo = new PayInfo();
        payInfo.setUid(order.getUid());
        payInfo.setOrderId(order.getOrderId());
        payInfo.setPayPlatform(Const.PayPlatformEnum.ALIPAY.getCode());
        payInfo.setPlatformNumber(tradeNo);
        payInfo.setPlatformStatus(tradeStatus);
        payInfo.setCreateTime(new Date());
        payInfoDao.save(payInfo);
        logger.debug("添加支付信息:"+payInfo);
    }

    @Override
    public Boolean queryOrderPayStatus(String orderId) {
        Order order = orderDao.findByOrderId(orderId);
        return order != null && order.getStatus() == Const.OrderStatusEnum.PAID.getCode();
    }
}
